#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "stdTcp.h"


struct StdTcpServer
{
    int sock;
};

// 监听
TcpS* TcpServerInit(const char *ip, unsigned short port)
{
    TcpS *s = (TcpS *)malloc(sizeof(TcpS));
    if (s == NULL)
    {
        printf("Tcps malloc error!\n");
        return NULL;
    }

    s->sock = socket(AF_INET, SOCK_STREAM, 0);
    if (s->sock < 0)
    {
        perror("socket error");
        free(s);
        return NULL;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip);

    if (bind(s->sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        perror("bind error");
        free(s);
        return NULL;
    }

    // 设置地址复用
    int on = 1;
    setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    {
        perror("setsockopt error");
        free(s);
        return NULL;
    }

    // 监听端口:最大等待队列
    if (listen(s->sock, 10) < 0)
    {
        perror("listen error");
        free(s);
        return NULL;
    }

    return s;

}

// 接收
int TcpServerAccept(TcpS * s)
{
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(clientAddr);
    int clientSock = accept(s->sock, (struct sockaddr*)&clientAddr, &len);
    if (clientSock < 0)
    {
        perror("accept error");
        return -1;
    }
    return clientSock;
}

bool TcpServerSend(int clientSock, void *p, size_t size)
{
    if (send(clientSock, p, size, 0) < 0)
    {
        /* code */
        perror("send error");
        return false;
    }
    return true;
}

bool TcpServerRecv(int clientSock, void *p, size_t size)
{
    if (recv(clientSock, p, size, 0) <= 0)
    {
        perror("recv error");
        return false;
    }

    return true;
}

void ClearTcpServer(TcpS *s)
{
    close(s->sock);
    free(s);
}

// 客户端
struct StdTcpClient
{
    int sock;
};

TcpC *TcpClientInit(const char *ServerIp, unsigned short ServerPort)
{
    TcpC * c = (TcpC *)malloc(sizeof(TcpC));
    if (c == NULL)
    {
        printf("TcpC malloc error!\n");
        return NULL;
    }

    c->sock = socket(AF_INET, SOCK_STREAM, 0);
    if (c->sock < 0)
    {
        perror("socket error");
        free(c);
        return NULL;
    }

    // 客户端连接服务器函数
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(ServerPort);
    addr.sin_addr.s_addr = inet_addr(ServerIp);

    if (connect(c->sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        perror("connect error");
        free(c);
        return NULL;
    }

    return c;
}

bool TcpClientSend(TcpC *c, void *p, size_t size)
{
    if (send(c->sock, p, size, 0) < 0)
    {
        /* code */
        perror("send error");
        return false;
    }
    return true;
}

bool TcpClientRecv(TcpC *c, void *p, size_t size)
{
    if (recv(c->sock, p, size, 0) <= 0)
    {
        perror("recv error");
        return false;
    }

    return true;
}

void ClearTcpClient(TcpC *c)
{
    close(c->sock);
    free(c);
}
